#!/bin/sh

# ===========================================================================
# 功能: 项目启动脚本
# 作者: x
# 时间: 2024-06-20
# 注意: 脚本建议以root权限执行,
# 使用方式: 将此脚本放置在jar同级目录下 ./x.sh start 启动 stop 停止 restart 重启 status 状态 log 日志 back 备份
# ===========================================================================




#jar包名称  一般情况下只需要改这个地方  注意: 不可与服务器上的jar重名
AppName=gtgz.jar
#前端包名称,用于备份该文件夹
DistName=dist
#项目名称 同时也时 命令名称
PROJECT_NAME=xxx

# JVM参数
JVM_OPTS="-Dname=$AppName  -Duser.timezone=Asia/Shanghai -Xms128m -Xmx1024m"
#获取项目路径
APP_HOME=$(dirname "$(readlink -f "$0")")
TIME=`date +'%Y%m%d%H%M%S'`
#指定启动端口
SERVER_PORT=0
#指定日志地址
LOG_HOME=$APP_HOME/logs
#指定备份地址
BACK_HOME=$APP_HOME/back



echo "项目路径:$APP_HOME"

# 检查操作名和应用名是否提供
if [ -z "$1" ]; then
    echo -e "\033[0;31m 未输入操作名，请输入 {start|stop|restart|status|log|back} \033[0m"
    exit 1
fi


function path() {
  echo "cd $APP_HOME"
  pwd
}

function list() {
    find /usr/local/bin -type l
}

function createLink() {
     if [ -z "$PROJECT_NAME" ] || [ "$PROJECT_NAME" = "xxx" ]; then
          PROJECT_NAME=$(basename "$AppName" .jar)
    fi
    if [ ! -f "/usr/local/bin/$PROJECT_NAME" ]; then
        ln -s "$APP_HOME/x.sh" "/usr/local/bin/$PROJECT_NAME"
        if [ $? -ne 0 ]; then
            echo -e "\033[0;31m 创建快捷方式失败 \033[0m"
            exit 1
        else
            echo -e "\033[0;32m 创建快捷方式成功，现在可在命令行输入 $PROJECT_NAME \033[0m"
        fi
    fi
}

function getJar() {
    if [ -z "$AppName" ] || [ "$AppName" = "xxx.jar" ]; then
        echo -e "\033[0;31m 未输入应用名，尝试自动获取同级目录下的.jar 文件 \033[0m"
        query_path="$APP_HOME/*.jar"
        for file in $query_path; do
            if [ -f "$file" ]; then
                AppName=$(basename "$file") # 提取文件名，去掉路径
                echo -e "\033[0;32m 自动获取应用名成功: $AppName \033[0m"
                break
            fi
        done

        # 检查AppName是否已被成功赋值
        if [ -z "$AppName" ]; then
            echo -e "\033[0;31m 未找到有效的应用名 \033[0m"
            exit 1
        fi
    fi
}

function log() {
    if [ ! -d "$LOG_HOME" ]; then
        mkdir -p "$LOG_HOME" || { echo "创建 文件夹 失败"; return 1; }
    fi
    local logFile="$LOG_HOME/$AppName.log"
    if [ ! -f "$logFile" ]; then
        touch "$logFile" || { echo "文件 创建 错误"; return 1; }
    fi
    tail -f  "$logFile"
}

function back() {
    if [ ! -d "$BACK_HOME" ]; then
        mkdir $BACK_HOME
    fi
    cp $APP_HOME/$AppName $BACK_HOME/$TIME-$AppName
    if [ -d "$APP_HOME/$DistName" ]; then
        cp -r $APP_HOME/$DistName $BACK_HOME/$TIME-$DistName
    fi
    if [ $? -ne 0 ]; then
        echo "备份失败"
        exit 1
    else
        echo "备份成功"
    fi
}

function pid() {
    local PID=$(ps -ef | grep "[j]ava" | grep -w "$AppName" | grep -v grep | awk '{print $2}')
    if [ -n "$PID" ]; then
        echo "$PID"
    else
        echo "0"
    fi
}

function port() {
    local pid="$1"
    local output=$(lsof -nP -a -p "$pid" -i tcp 2>/dev/null)

    if [ -n "$output" ]; then
        local PORT=$(echo "$output" | awk '/LISTEN/{split($9, a, ":"); print a[2]}')
        if [ -n "$PORT" ]; then
            echo "$PORT"
        else
            echo "未找到监听的端口"
        fi
    else
        echo "无相关进程运行或未监听端口"
    fi
}

function start() {
    PID=$(pid)
    PORT=$(port $PID)
    if [ "$PID" != 0 ]; then
        echo "$AppName is already running..."
         echo "pid:$PID   port:$PORT"
    else
        if [ "$SERVER_PORT" != 0 ]; then
            nohup java $JVM_OPTS -jar $APP_HOME/$AppName --server.port=$SERVER_PORT > "$LOG_HOME/$AppName.log" 2>&1 &
        else
            nohup java $JVM_OPTS -jar $APP_HOME/$AppName > "$LOG_HOME/$AppName.log" 2>&1 &
        fi

        log
        echo "Start $AppName success..."
        echo "pid:$PID   port:$PORT"
    fi
}

function debug() {
    PID=$(pid)
    PORT=$(port $PID)

    if [ "$PID" != 0 ]; then
        echo "$AppName is already running..."
        echo "pid:$PID   port:$PORT"
    else
        DEBUG_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:12138"

        if [ "$SERVER_PORT" != 0 ]; then
            nohup java $JVM_OPTS $DEBUG_OPTS -jar $APP_HOME/$AppName --server.port=$SERVER_PORT > "$LOG_HOME/$AppName.log" 2>&1 &
        else
            nohup java $JVM_OPTS $DEBUG_OPTS -jar $APP_HOME/$AppName > "$LOG_HOME/$AppName.log" 2>&1 &
        fi

        log
        echo "Start $AppName in debug mode success..."
        echo "Debug port: 12138"
        echo "pid:$PID   port:$PORT"
    fi
}

function stop() {
    echo "Stopping $AppName"
     while true; do
         PID=$(pid)
         if [ "$PID" = 0 ]; then
             echo "$AppName already stopped."
             break
         fi
         echo "Sending termination signal to $AppName (pid:$PID)..."
         kill -TERM "$PID"

         echo "$AppName (pid:$PID) exiting..."
         while kill -0 "$PID" &> /dev/null; do
             sleep 1
         done
         echo "$AppName exited."
         break
     done
}

function quickStop() {
    echo "立即停止 $AppName"
    PID=$(pid)
    if [ "$PID" -eq 0 ]; then
        echo "$AppName 已经停止。"
    else
        echo "向 $AppName (pid:$PID) 发送强制终止信号..."
        kill -KILL "$PID"
        echo "$AppName (pid:$PID) 正在被强制终止..."
        if ! kill -0 "$PID" &> /dev/null; then
            echo "$AppName 已被强制终止。"
        else
            echo "未能成功终止 $AppName，可能需要进一步检查。"
        fi
    fi
}

function restart(){
    stop
    sleep 2
    start
}

function status(){
    PID=$(pid)
    PORT=$(port $PID)
    if [ $PID != 0 ];then
        echo -e "$AppName is \033[0;32m running... \033[0m"
        echo -e "pid:$PID   port:$PORT"
    else
        echo -e "$AppName is \033[0;31m  not running... \033[0m"
    fi
}

getJar

createLink

case $1 in
    start)
    start;;
    debug)
    debug;;
    stop)
    stop;;
    qstop)
    quickStop;;
    log)
    log;;
    pid)
    pid;;
    back)
    back;;
    restart)
    restart;;
    status)
    status;;
    path)
    path;;
    path)
    path;;
    *)

esac
